/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License, Version 1.0 only
 * (the "License").  You may not use this file except in compliance
 * with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */
/*
 * Copyright (c) 1998 by Sun Microsystems, Inc.
 * All rights reserved.
 */

#include <stdio.h>				/* for fprintf() */
#include <stdlib.h>				/* for malloc() */
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpcsvc/mount.h>


/*
 * XDR routines to handle mountlist structure
 *
 * These are iterative versions to avoid the stack-blowing problems of
 * the recursive routines generated by rpcgen.
 *
 * XXXX These should be removed when rpcgen is fixed to produce better
 * code in these circumstances.
 */


bool_t
xdr_mountlist(xdrs, objp)
	register XDR *xdrs;
	mountlist *objp;
{
	bool_t more_data;

	switch (xdrs->x_op) {

	case XDR_FREE: {
		mountbody *mb, *tmp;

		tmp = *objp;

		while (tmp != NULL) {
			mb = tmp;
			tmp = mb->ml_next;
			if (!xdr_name(xdrs, &mb->ml_hostname))
				return (FALSE);
			if (!xdr_dirpath(xdrs, &mb->ml_directory))
				return (FALSE);
			free(mb);
		}

		break;
	}

	case XDR_DECODE: {
		mountbody *mb;
		mountbody *mb_prev = NULL;

		for (;;) {
			if (!xdr_bool(xdrs, &more_data))
				return (FALSE);

			if (!more_data)
				break;

			mb = (mountbody *)malloc(sizeof (struct mountbody));
			if (mb == NULL) {
				fprintf(stderr,
				    "xdr_mountlist: out of memory\n");
				return (FALSE);
			}
			mb->ml_hostname = NULL;
			mb->ml_directory = NULL;
			mb->ml_next = NULL;

			if (mb_prev == NULL) {
				mb_prev = mb;
				*objp = mb;
			}

			if (!xdr_name(xdrs, &mb->ml_hostname))
				return (FALSE);
			if (!xdr_dirpath(xdrs, &mb->ml_directory))
				return (FALSE);

			if (mb_prev != mb) {
				mb_prev->ml_next = mb;
				mb_prev = mb;
			}
		}
		break;
	}

	case XDR_ENCODE: {
		mountbody *mb;

		mb = *objp;

		for (;;) {
			more_data = mb != NULL;

			if (!xdr_bool(xdrs, &more_data))
				return (FALSE);

			if (!more_data)
				break;

			if (!xdr_name(xdrs, &mb->ml_hostname))
				return (FALSE);
			if (!xdr_dirpath(xdrs, &mb->ml_directory))
				return (FALSE);

			mb = mb->ml_next;
		}
		break;
	}

	default:
		break;
	}

	return (TRUE);
}


/*
 * xdr_mountbody() is included here simply for backward compatibility. It is
 * no longer used by xdr_mountlist(), nor by any other SunOS routine as of
 * now.
 *
 * This is simply a copy of the rpcgen generated routine.
 */
bool_t
xdr_mountbody(xdrs, objp)
	register XDR *xdrs;
	mountbody *objp;
{
	if (!xdr_name(xdrs, &objp->ml_hostname))
		return (FALSE);
	if (!xdr_dirpath(xdrs, &objp->ml_directory))
		return (FALSE);
	if (!xdr_mountlist(xdrs, &objp->ml_next))
		return (FALSE);
	return (TRUE);
}
